﻿// ===============================================================================
// XCI.NET 西安交通信息WinForm开发框架 2018 版权所有
// ===============================================================================
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading.Tasks;

namespace XCI.Helper
{
    /// <summary>
    /// Timer操作类
    /// </summary>
    public static class TimerHelper
    {
        private static readonly Dictionary<string, System.Timers.Timer> timers = new Dictionary<string, System.Timers.Timer>();

        /// <summary>
        /// 延迟执行
        /// </summary>
        /// <param name="interval">延迟时间,毫秒</param>
        /// <param name="execute">执行函数</param>
        /// <param name="synchronizationCurrentContext">同步当前上下文,UI进程必须设为true</param>
        public static void DelayRun(int interval, Action execute, bool synchronizationCurrentContext = true)
        {
            Task.Delay(interval).ContinueWith(p =>
            {
                execute?.Invoke();
            }, TaskScheduler.FromCurrentSynchronizationContext());
        }

        /// <summary>
        /// 定时执行
        /// </summary>
        /// <param name="name">任务名称</param>
        /// <param name="interval">时间间隔</param>
        /// <param name="execute">执行函数</param>
        public static void TimerRun(string name, double interval, Action execute)
        {
            if (timers.ContainsKey(name)) return;
            var time = new System.Timers.Timer { Interval = interval };
            time.Elapsed += (s, e) =>
            {
                execute?.Invoke();
            };
            time.Start();
            timers[name] = time;
        }
    }

    /// <summary>
    /// 计时器简单包装(Timer是先等待再执行)
    /// </summary>
    public class SimpleTimer : IDisposable
    {
        private readonly System.Timers.Timer _time;
        private Action _callback;
        private bool _stop;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="autoReset">获取或设置一个布尔值，该值指示 System.Timers.Timer 是否应只引发一次 System.Timers.Timer.Elapsed 事件（(false)或重复 (true)）。</param>
        /// <param name="interval">获取或设置引发 System.Timers.Timer.Elapsed 事件的间隔（以毫秒为单位）。</param>
        /// <param name="callback">回调函数</param>
        private SimpleTimer(bool autoReset, double interval, Action callback)
        {
            _callback = callback;
            _time = new System.Timers.Timer();
            _time.AutoReset = autoReset;
            _time.Enabled = false;
            _time.Interval = interval;
            _time.Elapsed += _time_Elapsed;
        }

        /// <summary>
        /// Timer对象
        /// </summary>
        public System.Timers.Timer Timer => _time;

        /// <summary>
        /// 创建单次执行计时器
        /// </summary>
        /// <param name="interval">获取或设置引发 System.Timers.Timer.Elapsed 事件的间隔（以毫秒为单位）。</param>
        /// <param name="callback">回调函数</param>
        public static SimpleTimer OnceTimer(double interval, Action callback = null)
        {
            return new SimpleTimer(false, interval, callback);
        }

        /// <summary>
        /// 创建重复执行计时器
        /// </summary>
        /// <param name="interval">获取或设置引发 System.Timers.Timer.Elapsed 事件的间隔（以毫秒为单位）。</param>
        /// <param name="callback">回调函数</param>
        public static SimpleTimer LoopTimer(double interval, Action callback = null)
        {
            return new SimpleTimer(true, interval, callback);
        }

        public SimpleTimer SynchronizingObject(ISynchronizeInvoke syncObject)
        {
            _time.SynchronizingObject = syncObject;
            return this;
        }

        /// <summary>
        /// 设置回调函数
        /// </summary>
        /// <param name="callback">回调函数</param>
        public SimpleTimer Callback(Action callback)
        {
            _callback = callback;
            return this;
        }

        /// <summary>
        /// 开始计时器(在Interval间隔之后启动)
        /// </summary>
        public void Start()
        {
            _stop = false;
            _time.Start();
        }

        /// <summary>
        /// 停止计时器
        /// </summary>
        public void Stop()
        {
            _stop = true;
            _time.Stop();
        }

        /// <summary>
        /// 手动调用回调函数
        /// </summary>
        public void Invoke()
        {
            _callback?.Invoke();
        }

        /// <summary>执行与释放或重置非托管资源关联的应用程序定义的任务。</summary>
        public void Dispose()
        {
            _time.Dispose();
        }

        private void _time_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (_stop == false)
            {
                _callback?.Invoke();
            }
        }
    }

    /// <summary>
    /// 延迟执行计时器
    /// </summary>
    public class DelayTimer : IDisposable
    {
        private Action callback;
        private readonly System.Windows.Forms.Timer timer;
        private bool isStop;

        public DelayTimer(int interval, Action callback)
        {
            this.callback = callback;
            this.timer = new System.Windows.Forms.Timer { Interval = interval, Enabled = false };
            this.timer.Tick += Timer_Tick;
        }

        private void Timer_Tick(object sender, EventArgs e)
        {
            if (this.isStop) return;
            this.timer.Stop();
            this.callback?.Invoke();
        }

        /// <summary>
        /// 设置回调函数
        /// </summary>
        /// <param name="callbackfn">回调函数</param>
        public DelayTimer Callback(Action callbackfn)
        {
            this.callback = callbackfn;
            return this;
        }

        /// <summary>
        /// 开始计时器(在Interval间隔之后启动)
        /// </summary>
        public void Start()
        {
            this.isStop = false;
            this.timer.Stop();
            this.timer.Start();
        }

        /// <summary>
        /// 停止计时器
        /// </summary>
        public void Stop(Action stopCallback = null)
        {
            this.isStop = true;
            this.timer.Stop();
            stopCallback?.Invoke();
        }

        /// <summary>
        /// 手动调用回调函数
        /// </summary>
        public void Invoke()
        {
            this.callback?.Invoke();
        }

        /// <summary>执行与释放或重置非托管资源关联的应用程序定义的任务。</summary>
        public void Dispose()
        {
            timer.Dispose();
        }
    }
}